#include "espressif/esp_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "factory.h"
#include "user_config.h"
#include "driver/uart.h"
#include "driver/gpio.h"

et_uint32 key_test_timeout_flag=0;
LOCAL os_timer_t key_test_timer;
extern et_uint32 audio_voice_data;
extern et_int64 file_total_size;
extern et_uint32 write_flash_end;
extern xQueueHandle xQueueUart;
extern et_int32 read_uart_data_flag;
static et_uchar fac_uart_recv_buff[UART_MAX_READ_BUFFER] = {0};

SpiFlashOpResult get_uid(id_info_t *uid)
{
	SpiFlashOpResult rc=SPI_FLASH_RESULT_OK;
	
	rc = spi_flash_read(APPKEY_UID_FASH_SECTOR * SPI_FLASH_SEC_SIZE, (et_uint32 *)uid, sizeof(id_info_t));
	
	return rc;
}

static SpiFlashOpResult set_uid(id_info_t *uid)
{
	SpiFlashOpResult rc=SPI_FLASH_RESULT_OK;
	
	rc = spi_flash_erase_sector(APPKEY_UID_FASH_SECTOR);
	if(rc != SPI_FLASH_RESULT_OK)
		return rc;
	
	rc = spi_flash_write(APPKEY_UID_FASH_SECTOR * SPI_FLASH_SEC_SIZE, (et_uint32 *)uid, sizeof(id_info_t));
	if(rc != SPI_FLASH_RESULT_OK)
		return rc;

	return rc;
}

SpiFlashOpResult get_fac_norm_mode(et_uchar *result)
{
	SpiFlashOpResult rc=SPI_FLASH_RESULT_OK;
	et_uchar fac_norm_mode[FAC_NORM_MODE_LEN]={0};
	
	rc = spi_flash_read(MODE_INFO_FLASH_SECTOR * SPI_FLASH_SEC_SIZE, (et_uint32 *)fac_norm_mode, sizeof(fac_norm_mode));
	if(rc != SPI_FLASH_RESULT_OK)
	{
		*result = NORM_MODE;
		return rc;
	}

	if(!strncmp(fac_norm_mode, FACTORY, strlen(FACTORY)))
	{
		*result = FAC_MODE;
	}
	else if(!strncmp(fac_norm_mode, NORMAL, strlen(NORMAL)))
	{
		*result = NORM_MODE;
	}
	else
	{
		*result = NORM_MODE;
		printf("mode error, default normal mode, fac_norm_mode = %s\n", fac_norm_mode);
	}
	
	return rc;
}

static SpiFlashOpResult set_fac_norm_mode(et_uchar *fac_norm_mode)
{
	SpiFlashOpResult rc=SPI_FLASH_RESULT_OK;
	
	rc = spi_flash_erase_sector(MODE_INFO_FLASH_SECTOR);
	if(rc != SPI_FLASH_RESULT_OK)
		return rc;

	rc = spi_flash_write(MODE_INFO_FLASH_SECTOR * SPI_FLASH_SEC_SIZE, (et_uint32 *)fac_norm_mode, FAC_NORM_MODE_LEN);
	if(rc != SPI_FLASH_RESULT_OK)
		return rc;
	
	return rc;
}

void ICACHE_FLASH_ATTR key_test_timer_func(void)
{
	key_test_timeout_flag = 1;
}


static et_int32 ack_to_uart(et_uchar *msg_buf, et_uchar *ack_buf, et_int32 rc)
{
	et_int32 len=START_LEN;
	
	ack_buf[0] = 0xFF;
	ack_buf[1] = 0xFF;
	ack_buf[2] = 0x00;
	ack_buf[3] = ACK_ERROR_LEN;
	ack_buf[4] = msg_buf[4] | 0x0F;
	ack_buf[5] = msg_buf[5];
	ack_buf[6] = msg_buf[6];
	ack_buf[7] = rc;
	ack_buf[8] = check_sum(&ack_buf[2], ACK_ERROR_LEN + 1);
	len += ACK_ERROR_LEN;
	
	return len;
	
}

static et_int32 ack_temp_hum_to_uart(et_uchar *msg_buf, et_uchar *temp_hum, et_uchar *ack_buf, et_uchar rc)
{
	et_int32 len=START_LEN;
	
	ack_buf[0] = 0xFF;
	ack_buf[1] = 0xFF;
	ack_buf[2] = 0x00;
	ack_buf[3] = ACK_TEMP_HUM_LEN;
	ack_buf[4] = msg_buf[4] | 0x0F;
	ack_buf[5] = msg_buf[5];
	ack_buf[6] = msg_buf[6];
	ack_buf[7] = rc;
	ack_buf[8] = ascii_2_dec(temp_hum[0]);   //we transform to 8421bcd 0x50
	ack_buf[9] = ascii_2_dec(temp_hum[1]);
	ack_buf[10] = ascii_2_dec(temp_hum[2]);
	ack_buf[11] = ascii_2_dec(temp_hum[3]);
	ack_buf[12] = check_sum(&ack_buf[2], ACK_TEMP_HUM_LEN + 1);
	len += ACK_TEMP_HUM_LEN; 

	return len;
}

static et_int32 ack_barometric_to_uart(et_uchar *msg_buf, et_int32 barometric, et_uchar *ack_buf, et_uchar rc)
{
	et_uchar baro[4];
	et_int32 i, tmp, len=START_LEN;

	tmp = ascii_2_dec(barometric);
	for(i = 0; i < 4; i++)
    		baro[i] = tmp >> (3 - i) * 8;

	ack_buf[0] = 0xFF;
	ack_buf[1] = 0xFF;
	ack_buf[2] = 0x00;
	ack_buf[3] = ACK_BAROMETRIC_TEST_LEN;
	ack_buf[4] = msg_buf[4] | 0x0F;
	ack_buf[5] = msg_buf[5];
	ack_buf[6] = msg_buf[6];
	ack_buf[7] = rc;
	ack_buf[8] = baro[0];
	ack_buf[9] = baro[1];
	ack_buf[10] = baro[2];
	ack_buf[11] = baro[3];
	ack_buf[12] = check_sum(&ack_buf[2], ACK_BAROMETRIC_TEST_LEN + 1);
	len += ACK_BAROMETRIC_TEST_LEN; 

	return len;
}

static et_int32 ack_uid_to_uart(et_uchar *msg_buf, id_info_t *uid, et_uchar *ack_buf, et_uchar rc)
{	
	et_int32 len=START_LEN, pos=8;
	
	ack_buf[0] = 0xFF;
	ack_buf[1] = 0xFF;
	ack_buf[2] = 0x00;
	ack_buf[3] = ACK_UID_LEN;
	ack_buf[4] = msg_buf[4] | 0x0F;
	ack_buf[5] = msg_buf[5];
	ack_buf[6] = msg_buf[6];
	ack_buf[7] = rc;

	memcpy(&ack_buf[pos], uid->appkey, APPKEY_LEN);
	pos += APPKEY_LEN;
	memcpy(&ack_buf[pos], uid->uid, UID_LEN);
	pos += UID_LEN;
	ack_buf[pos] = check_sum(&ack_buf[2], ACK_UID_LEN + 1);
	len += ACK_UID_LEN; 
	
	return len;
}

static et_int ack_key_to_uart(et_uchar *msg_buf, et_uchar key_ok, et_uchar *ack_buf, et_uchar rc)
{
	et_int32 len=START_LEN;
	
	ack_buf[0] = 0xFF;
	ack_buf[1] = 0xFF;
	ack_buf[2] = 0x00;
	ack_buf[3] = ACK_KEY_LEN;
	ack_buf[4] = msg_buf[4] | 0x0F;
	ack_buf[5] = msg_buf[5];
	ack_buf[6] = msg_buf[6];
	ack_buf[7] = rc;
	ack_buf[8] = msg_buf[7];
	ack_buf[9] = key_ok;
	ack_buf[10] = check_sum(&ack_buf[2], ACK_KEY_LEN + 1);
	len += ACK_KEY_LEN; 
	
	return len;
}

static et_int ack_mode_to_uart(et_uchar *msg_buf, et_uchar result, et_uchar *ack_buf, et_uchar rc)
{
	et_int32 len=START_LEN;
	
	ack_buf[0] = 0xFF;
	ack_buf[1] = 0xFF;
	ack_buf[2] = 0x00;
	ack_buf[3] = ACK_MODE_LEN;
	ack_buf[4] = msg_buf[4] | 0x0F;
	ack_buf[5] = msg_buf[5];
	ack_buf[6] = msg_buf[6];
	ack_buf[7] = rc;
	ack_buf[8] = result;
	ack_buf[9] = check_sum(&ack_buf[2], ACK_MODE_LEN + 1);
	len += ACK_MODE_LEN; 
	
	return len;
}

et_int32 parse_msg_from_uart(et_uchar *msg_buf, et_int32 data_len)
{
	et_int32 i, pos=0, rc = -1;
	et_uchar cmd, type, bcc;
	et_int32 len, seq;
	msg_to_net_t *msg=NULL;

	#ifdef USER_PRINT_DEBUG
	print_hex("msg_buf", msg_buf, data_len);
	#endif
	
	if(msg_buf[pos] != 0xFF ||msg_buf[pos + 1] != 0xFF) 
	{
		os_printf("parse packet head error\n");
		return rc;
	}
	pos += 2;
	
	len = (msg_buf[pos] << 8) | msg_buf[pos + 1];
	if(len < 3 || len != data_len - 2 - 2) 
	{
		os_printf("parse packet length error\n");
		return rc;
	}

	bcc = check_sum(&msg_buf[pos], len + 2 - 1);
	if(bcc != msg_buf[data_len - 1]) 
	{
		msg = (msg_to_net_t *)malloc(sizeof(msg_to_net_t));
		if(msg == NULL) 
		{
			os_printf("malloc msg error\n");
			return rc;
		}	

		msg->len = ack_to_uart(msg_buf, msg->buf, ACK_BCC_ERROR);
		os_printf("bcc error\n");
		uart_send(msg->buf, msg->len);
		free(msg);
		return rc;
	}
	
	pos += 2;
	
	cmd = msg_buf[pos];
	pos += 1;
	
	seq += msg_buf[pos];
	pos += 1;

	type = msg_buf[pos];
	pos += 1;	

	switch(cmd) 
	{
		case CMD_CONTROL: 
		{	
			switch(type) 
			{
				case TYPE_RGB_LIGHT_DEV: 
				{
					et_uchar red;
					et_uchar gre;
					et_uchar blu;
				
					red = msg_buf[pos];
					pos += 1;
					gre = msg_buf[pos];
					pos += 1;
					blu = msg_buf[pos];
					
					#ifdef USER_PRINT_DEBUG
					os_printf("red =%2x, gre=%2x, blu=%2x\n", red, gre, blu);
					#endif
					
					RGB_light_init();		// RGB init
				 	rc = ACK_TO_UART;
				}
					break;

				case TYPE_AUDIO_DEV:
				{
					audio_init();
					delay_s(10);
					
					file_total_size = TEST_AUDIO_LEN;
					audio_voice_data = 1;           //to inform interrupt of voice data coming 
					write_flash_end = 1; 
					rc = ACK_TO_UART;
				}
					break;

				case TYPE_OLED_DEV:
				{
					extern et_uchar BMP1[];
					et_uint32 len = 1024;	// BMP1 member
					
					i2c_master_gpio_init(); // I2C init
					OLED_init(); 			// OLED init
					OLED_show_bmp(0, 0, 128, 8, BMP1, len);
					rc = ACK_TO_UART;
				}
					break;

				default:
					break;
			}
		}
			break;
			
		case CMD_QUERY: 
		{
			msg = (msg_to_net_t *)malloc(sizeof(msg_to_net_t));
			if(msg == NULL) 
			{
				os_printf("malloc msg error\n");
				return rc;
			}	
			
			switch(type) 
			{			
				case TYPE_TEMP_HUM_SENSOR:
				{
					et_uchar temp_hum[HUM_DATA_SIZE]={0};

					if(DHT11_read_temp_hum(temp_hum, HUM_DATA_SIZE) != RETURN_OK) 
					{
						os_printf("DHT11_read_temp_hum error\n");
						msg->len = ack_to_uart(msg_buf, msg->buf, ACK_DEV_FAILED);
						rc = msg->len;
						uart_send(msg->buf, msg->len);
						free(msg);
						break;
					}

					msg->len = ack_temp_hum_to_uart(msg_buf, temp_hum, msg->buf, ACK_SUCCESS);
					rc = msg->len;
					uart_send(msg->buf, msg->len);
					free(msg);
				}
					break;
			
				case TYPE_BAROMETRIC_SENSOR: 
				{
					et_long32 barometric=0, temperature=0;

					i2c_master_gpio_init();
					barometric = barometric_collect(&temperature);
					if(barometric == -1) 
					{
						os_printf("barometric_collect error\n");
						msg->len = ack_to_uart(msg_buf, msg->buf, ACK_DEV_FAILED);
						rc = msg->len;
						uart_send(msg->buf, msg->len);
						free(msg);
						break;
					}
					msg->len = ack_barometric_to_uart(msg_buf, (et_int32)barometric, msg->buf, ACK_SUCCESS);
					rc = msg->len;
					uart_send(msg->buf, msg->len);
					free(msg);				
				}
					break;

				case TYPE_VERSION_UID: 
				{
					id_info_t *uid=NULL;

					uid = (id_info_t *)malloc(sizeof(id_info_t));
					if(uid == NULL)
					{
						os_printf("malloc query uid error\n");
						return rc;
					}

					memset(uid, 0, sizeof(id_info_t));
					if(get_uid(uid) != SPI_FLASH_RESULT_OK) 
					{
						os_printf("get_uid error\n");
						msg->len = ack_to_uart(msg_buf, msg->buf, ACK_DEV_FAILED);
						rc = msg->len;
						uart_send(msg->buf, msg->len);
						free(uid);
						free(msg);			
						break;
					}

					msg->len = ack_uid_to_uart(msg_buf, uid, msg->buf, ACK_SUCCESS);
					rc = msg->len;
					uart_send(msg->buf, msg->len);
					free(uid);
					free(msg);			
				}
					break;

				case TYPE_KEY: 
				{ 
					et_uchar value=0, key_test=0, key_ok=0;
					key_gpio_t key;
		
					key_test = msg_buf[pos];
					switch(key_test) 
					{
						case KEY_A: 
						{
							key.key_gpio_pin = AIRKISS_KEY_IO_PIN;
							key.key_num = AIRKISS_KEY_IO_NUM;
							airkiss_key_init(&key);
							value = gpio_get_value(AIRKISS_KEY_IO_NUM); // 1
							
							os_timer_disarm(&key_test_timer);
   							os_timer_setfn(&key_test_timer, (os_timer_func_t *)key_test_timer_func, NULL);
   							os_timer_arm(&key_test_timer, 5000, 0);
							
							while(1) 
							{
								if(key_test_timeout_flag)
								{
									key_test_timeout_flag = 0;
									key_ok = 0;
									msg->len = ack_key_to_uart(msg_buf, key_ok, msg->buf, ACK_SUCCESS);
									rc = msg->len;
									uart_send(msg->buf, msg->len);
									free(msg);	
									break;
								}
								
								if(value !=  gpio_get_value(AIRKISS_KEY_IO_NUM))
								{
									delay_ms(10);
									if(value !=  gpio_get_value(AIRKISS_KEY_IO_NUM)) 
									{
										key_ok = 1;
										msg->len = ack_key_to_uart(msg_buf, key_ok, msg->buf, ACK_SUCCESS);
										rc = msg->len;
										uart_send(msg->buf, msg->len);
										free(msg);	
										os_timer_disarm(&key_test_timer);
										break;
									}
								}
								
								delay_ms(20);
							}
							
						}
							break;
							
						case KEY_B:
						{
							gpio16_input_conf();
							value = gpio16_input_get(); 
							
							os_timer_disarm(&key_test_timer);
   							os_timer_setfn(&key_test_timer, (os_timer_func_t *)key_test_timer_func, NULL);
   							os_timer_arm(&key_test_timer, 5000, 0);

							while(1) 
							{
								if(key_test_timeout_flag)
								{
									key_test_timeout_flag = 0;
									key_ok = 0;
									msg->len = ack_key_to_uart(msg_buf, key_ok, msg->buf, ACK_SUCCESS);
									rc = msg->len;
									uart_send(msg->buf, msg->len);
									free(msg);	
									break;
								}
								
								if(value !=  gpio16_input_get())
								{
									delay_ms(10);
									if(value !=  gpio16_input_get()) 
									{
										key_ok = 1;
										msg->len = ack_key_to_uart(msg_buf, key_ok, msg->buf, ACK_SUCCESS);
										rc = msg->len;
										uart_send(msg->buf, msg->len);
										free(msg);	
										os_timer_disarm(&key_test_timer);
										break;
									}
								}
								
								delay_ms(20);
							}
						}
							break;

						default:
							break;
					}
				}
					break;

				case TYPE_FAC_NORM_MODE:
				{
					et_uchar result=0;
						
					if(get_fac_norm_mode(&result) != SPI_FLASH_RESULT_OK) 
					{
						os_printf("get_uid error\n");
						msg->len = ack_to_uart(msg_buf, msg->buf, ACK_DEV_FAILED);
						rc = msg->len;
						uart_send(msg->buf, msg->len);
						free(msg);			
						break;
					}

					msg->len = ack_mode_to_uart(msg_buf, result, msg->buf, ACK_SUCCESS);
					rc = msg->len;
					uart_send(msg->buf, msg->len);
					free(msg);	
				}	
					break;
				
				default:
					break;
			}
		}
			break;

		case CMD_SETUP:
		{			
			msg = (msg_to_net_t *)malloc(sizeof(msg_to_net_t));
			if(msg == NULL) 
			{
				os_printf("malloc msg error\n");
				return rc;
			}

			switch(type)
			{
				case TYPE_VERSION_UID:
				{
					id_info_t *uid=NULL;

					uid = (id_info_t *)malloc(sizeof(id_info_t));
					if(uid == NULL)
					{
						printf("mallloc set uid error!!!\n");
						return rc;
					}

					memset(uid, 0, sizeof(id_info_t));
					memcpy(uid->appkey, &msg_buf[pos], APPKEY_LEN);
					pos += APPKEY_LEN;
					memcpy(uid->uid, &msg_buf[pos], UID_LEN);
					
					if(set_uid(uid) != SPI_FLASH_RESULT_OK)
					{
						os_printf("set_uid error\n");
						msg->len = ack_to_uart(msg_buf, msg->buf, ACK_DEV_FAILED);
						rc = msg->len;
						uart_send(msg->buf, msg->len);
						free(uid);
						free(msg);			
						break;
					}
					
					msg->len = ack_to_uart(msg_buf, msg->buf, ACK_SUCCESS);
					rc = msg->len;
					uart_send(msg->buf, msg->len);
					free(uid);
					free(msg);
					
				}
					break;
					
				case TYPE_FAC_NORM_MODE:
				{
					et_uchar result=0;
					et_uchar fac_norm_mode[FAC_NORM_MODE_LEN]={0};

					result = msg_buf[pos];
					switch(result)
					{
						case FAC_MODE:
						{
							strcpy(fac_norm_mode, FACTORY);
							if(set_fac_norm_mode(fac_norm_mode) != SPI_FLASH_RESULT_OK)
							{
								os_printf("set_fac_norm_mode error\n");
								msg->len = ack_to_uart(msg_buf, msg->buf, ACK_DEV_FAILED);
								rc = msg->len;
								uart_send(msg->buf, msg->len);
								free(msg);			
								break;
							}

							msg->len = ack_to_uart(msg_buf, msg->buf, ACK_SUCCESS);
							rc = msg->len;
							uart_send(msg->buf, msg->len);
							free(msg);	
						}
							break;

						case NORM_MODE:
						{
							strcpy(fac_norm_mode, NORMAL);
							if(set_fac_norm_mode(fac_norm_mode) != SPI_FLASH_RESULT_OK)
							{
								os_printf("set_fac_norm_mode error\n");
								msg->len = ack_to_uart(msg_buf, msg->buf, ACK_DEV_FAILED);
								rc = msg->len;
								uart_send(msg->buf, msg->len);
								free(msg);			
								break;
							}

							msg->len = ack_to_uart(msg_buf, msg->buf, ACK_SUCCESS);
							rc = msg->len;
							uart_send(msg->buf, msg->len);
							free(msg);	
						}
							break;
							
						default:
							break;
					}
				}
					break;

				default:
					break;
				
			}
			
		}
			break;

		default:
		{
			msg = (msg_to_net_t *)malloc(sizeof(msg_to_net_t));
			if(msg == NULL) 
			{
				os_printf("malloc msg error\n");
				return rc;
			}	

			msg->len = ack_to_uart(msg_buf, msg->buf, ACK_CMD_ILLIGAL);
			rc = msg->len;
			uart_send(msg->buf, msg->len);
			free(msg);
		}
			break;
	}

	return rc;
}

et_int32 read_uart_packet(et_uchar *read_buf, et_int32 *buf_len)
{
   	et_int32 rc = ET_FAILURE;
    	et_int32 len=0, msg_len=0;
	et_int32 count = 0;
	et_int32 head_flag = 0;
	
	do
	{
		len = recv_data_uart(read_buf, 2, 100);
		if(len <= 0)
		{	
			os_printf("fail len is %d\n", len);
			rc = ET_BUFFER_OVERFLOW;
			return rc;
		}
		
		if(read_buf[0] != 0xFF || read_buf[1] != 0xFF)
		{
			os_printf("uart packet head error\n");
			count++;
		}
		else
		{
			head_flag = 1;
		}
		
	}while(head_flag != 1 && count < 100);

	if(head_flag != 1)
	{
		os_printf("uart packet head error and len is more than 200 bytes\n");
		return rc;
	}

	len = recv_data_uart(read_buf + 2, 2, 100);
	if(len  != 2)
	{
		os_printf("uart packet length is not with 2 bytes\n");
		return rc;
	}
	
	msg_len = (read_buf[2] << 8) | read_buf[3];
	len = recv_data_uart(read_buf + START_LEN, msg_len, msg_len * 50);
	
	if((msg_len <= 3) || (msg_len  != len))
	{
		os_printf("read packet head error\n");
		return rc;
	}

	*buf_len = len + START_LEN;
	rc = ET_SUCCESS;
		
	return rc;
}

void fac_read_uart_task(void *pvParameters)
{
	os_event_t e;
	et_int32 rc = ET_FAILURE;
	et_int32 buf_len=0;
	
	for (;;) 
	{
		if (xQueueReceive(xQueueUart, (void *)&e, (portTickType)portMAX_DELAY)) 
		{
			switch (e.event)
			{
				case UART_EVENT_RX_CHAR:
				{
					memset(fac_uart_recv_buff,0,sizeof(fac_uart_recv_buff));
					read_uart_data_flag = 1;
					rc = read_uart_packet(fac_uart_recv_buff, &buf_len);
					read_uart_data_flag = 0;

					if(rc == ET_SUCCESS)
					{
						rc = parse_msg_from_uart(fac_uart_recv_buff, buf_len);
						if(rc <= 0)
						{
							os_printf("parse_msg_from_uart error!!!\n");
							break;
						}
					}
				}
				break;

				default:
				    break;
			}
		}
	}

    vTaskDelete(NULL);
}